import { Action } from "../Action/Action";
import { BehaviourTreeBase } from "../BehaviorNode";
import { Precondition } from "../Condition/Condition";
import { RunStatus } from "../IBehaviourTree";
import { Sequence } from "./Sequence";
/**
action = root.findNextAction(input);
if action is not empty then
action.Execute(request,  input)  //request是输出的请求
else
print “no action is available”
 */


export class Composite {
    children: BehaviourTreeBase
    nodeList: BehaviourTreeBase[] = [];
    conditionList: Precondition[] = [];
    status: RunStatus = RunStatus.Completed;
    nodeName: string = 'Selector';
    runIdx: number = 0;
    constructor(nodeName: string) {
        this.nodeName = nodeName;
    }
    checkCondition() {
        return !!this.conditionList.find(v => {
            return v.externalCondition();
        })
    }
    findNextAction() {
        let actionNode: Action;
        this.status = RunStatus.Running;
        if (!this.checkCondition()) {
            this.status = RunStatus.Failure;
        } else {
            this.status = RunStatus.Completed;
        }
        /**检查子节点 */
        if (this.status == RunStatus.Completed) {
            this.runIdx = 0;
            do {
                let childNode = this.nodeList[this.runIdx];
                actionNode = childNode.findNextAction();
                this.runIdx++;
            } while (this.runIdx <= this.nodeList.length - 1 && !actionNode)
        }
        return actionNode;
    }
    enter(): boolean {
        let checkOk = this.checkCondition();
        if (!checkOk) return false;

        return true
    }
    leave(): boolean {
        return true
    }
    tick(): RunStatus {
        this.runIdx = 0;
        this.status = RunStatus.Completed;
        if (!this.checkCondition()) {
            this.status = RunStatus.Failure;
            return this.status;
        }
        /**检查子节点 */
        do {
            this.status = this.nodeList[this.runIdx].tick();
            this.runIdx++;
        } while (this.status == RunStatus.Failure)

        return this.status;
    }

    execCondition(): boolean {
        let res = !!this.conditionList.find(v => {
            return v.externalCondition();
        })
        return res;
    }

    addNode(node: BehaviourTreeBase): void {
        this.nodeList.push(node);
    }
    removeNode(node: BehaviourTreeBase): void {
        if (this.nodeList.includes(node)) {
            this.nodeList.splice(this.nodeList.indexOf(node), 1);
        }
    }
    HasNode(node: BehaviourTreeBase): boolean {
        return this.nodeList.includes(node);
    }

    addCondition(condition: Precondition): void {
        this.conditionList.push(condition);
    }
    removeCondition(condition: Precondition): void {
        if (this.conditionList.includes(condition)) {
            this.conditionList.splice(this.conditionList.indexOf(condition), 1);
        }
    }
    hasCondition(condition: Precondition): boolean {
        return this.conditionList.includes(condition);
    }
}